home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************
- #
- # JPEG.c
- #
- # This segment handles JPEG.
- #
- # Author(s): Michael Marinkovich
- # Apple Developer Technical Support
- # marink@apple.com
- #
- # Modification History:
- #
- # 4/3/96 MWM Initial coding
- #
- # Copyright © 1992-96 Apple Computer, Inc., All Rights Reserved
- #
- #
- # You may incorporate this sample code into your applications without
- # restriction, though the sample code has been provided "AS IS" and the
- # responsibility for its operation is 100% yours. However, what you are
- # not permitted to do is to redistribute the source as "DSC Sample Code"
- # after having made changes. If you're going to re-distribute the source,
- # we require that you make it clear in the source that the code was
- # descended from Apple Sample Code, but that you've made changes.
- #
- *************************************************************************************/
-
-
- #include <Events.h>
- #include <ToolUtils.h>
- #include <Gestalt.h>
- #include <OSUtils.h>
- #include <Palettes.h>
-
- #include "App.h"
- #include "Proto.h"
-
- // data unload buffer size
- #define kBufferSize codecMinimumDataSize
-
-
- //----------------------------------------------------------------------
- // Globals
- //----------------------------------------------------------------------
-
- extern Boolean gInBackground;
-
-
-
- //----------------------------------------------------------------------
- //
- // OpenJPEGFile - open a JPEG file with supplied FSSpec.
- //
- //
- //----------------------------------------------------------------------
-
- CGrafPtr OpenJPEGFile(FSSpec spec, OSErr *theErr)
- {
- OSErr err = noErr;
- Handle tempHandle;
- Handle newHandle;
- GWorldPtr theWorld = nil;
- short refNum;
- long fileSize;
- Size pictSize;
-
- SetCursor(*GetCursor(watchCursor)); // set the cursor to a watch while busy
-
- err = FSpOpenDF(&spec, fsRdWrShPerm, &refNum);
- if ( err == noErr )
- {
- err = GetEOF(refNum, &fileSize );
- if ( err == noErr )
- {
- tempHandle = NewHandle(fileSize);
- if (tempHandle == nil)
- {
- tempHandle = TempNewHandle(fileSize, &err); // allocate space for picture
- }
-
- if ( err == noErr && tempHandle != nil )
- {
- HLock(tempHandle);
- err = FSRead(refNum, &fileSize, *tempHandle); // read in the pict data
- HUnlock(tempHandle);
- }
- }
- FSClose(refNum); // close the file
-
- theWorld = ConvertJPEG(tempHandle);
-
- }
-
- SetCursor(&qd.arrow ); // set cursor back to arrow
-
- *theErr = err;
-
- return theWorld;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // ConvertJPEG - Convert JPEG data to a PICT.
- //
- //
- //----------------------------------------------------------------------
-
- CGrafPtr ConvertJPEG(Handle image)
- {
- OSErr err = noErr;
- GWorldPtr oldPort;
- GWorldPtr theWorld;
- GDHandle oldGD;
- PixMapHandle thePix;
- ImageDescriptionHandle desc = nil;
- Rect bounds;
-
- GetGWorld(&oldPort, &oldGD);
-
- HLock((Handle)image);
- desc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
-
- if (desc != nil)
- {
- err = GetJPEGDescription(image, desc, &bounds);
- theWorld = NewJPEGWorld((*desc)->depth, bounds);
-
- if (theWorld != nil)
- {
- thePix = GetGWorldPixMap(theWorld);
- LockPixels(thePix);
- SetGWorld(theWorld, nil);
-
- err = DecompressImage(*image, desc, thePix, &bounds, &bounds, srcCopy, nil);
-
- UnlockPixels(thePix);
-
- }
- DisposeHandle((Handle)desc);
-
- }
-
- SetGWorld(oldPort, oldGD);
-
- return theWorld;
- }
-
-
- //----------------------------------------------------------------------
- //
- // GetJPEGDescription -
- //
- //
- //----------------------------------------------------------------------
-
- OSErr GetJPEGDescription(Handle image, ImageDescriptionHandle desc, Rect *bounds)
- {
- OSErr err = noErr;
- Fixed xRes,yRes;
- long i;
- long imageSize;
- unsigned char *buffer;
- char JIFF[5];
- short w = 0, h = 0;
- short units;
- short version;
- short components;
-
- buffer = (unsigned char *)(*image);
- imageSize = GetHandleSize((Handle)image);
-
- for (i = 0; i < imageSize; i++ )
- {
- if (buffer[i] == 0xff)
- {
- i++;
- if (buffer[i] == 0xc0) // start of frame header marker
- {
- i += 4;
- h = (buffer[i]<<8) | buffer[i+1];
- i += 2;
- w = (buffer[i]<<8) | buffer[i+1];
- i += 2;
- if ( w && h ) // make sure we do have something to display
- {
- /* now make up the image description */
- (*desc)->idSize = sizeof(ImageDescription);
- (*desc)->temporalQuality = 0;
- (*desc)->spatialQuality = codecNormalQuality;
- (*desc)->dataSize = imageSize;
- (*desc)->cType = 'jpeg';
- (*desc)->version = 0;
- (*desc)->revisionLevel = 0;
- (*desc)->vendor = 0;
- (*desc)->width = w;
- (*desc)->height = h;
- (*desc)->clutID = -1;
- BlockMove("\pPhoto - JPEG",(*desc)->name,13);
- (*desc)->hRes = xRes;
- (*desc)->vRes = yRes;
-
- components = buffer[i++];
-
- switch (components)
- {
- case 3:
- (*desc)->depth = 32;
- break;
-
- case 1:
- (*desc)->depth = 40;
- break;
-
- default:
- break;
- }
-
- SetRect(bounds, 0, 0, w, h);
- return noErr;
- }
- }
- if (buffer[i] == 0xe0) // JFIF marker
- {
- i += 3;
- JIFF[0] = buffer[i++];
- JIFF[1] = buffer[i++];
- JIFF[2] = buffer[i++];
- JIFF[3] = buffer[i++];
- JIFF[4] = buffer[i++];
-
- // check if we really have the JFIF header
- if ( JIFF[0] == 'J' && JIFF[1] == 'F' && JIFF[2] == 'I' && JIFF[3] == 'F' )
- {
- version = (buffer[i]<<8) | buffer[i+1];
- i += 2;
-
- if ( version < 0x100 )
- {
- err = paramErr;
- break; // don't know this
- }
-
- units = buffer[i++];
- xRes = (buffer[i]<<8) | buffer[i+1];
- i += 2;
- yRes = (buffer[i]<<8) | buffer[i+1];
- i += 2;
-
- switch ( units )
- {
- case 0: // no res, just aspect ratio
- xRes = FixMul(72L << 16, xRes << 16);
- yRes = FixMul(72L << 16, yRes << 16);
- break;
-
- case 1: // dots per inch
- xRes = xRes << 16;
- yRes = yRes << 16;
- break;
-
- case 2: // dots per centimeter (we convert to dpi )
- xRes = FixMul(0x28a3d, xRes << 16);
- yRes = FixMul(0x28a3d, xRes << 16);
- break;
-
- default:
- break;
- }
- }
- }
- }
- }
-
- return err;
- }
-
-
- //----------------------------------------------------------------------
- //
- // NewJPEGWorld -
- //
- //
- //----------------------------------------------------------------------
-
- GWorldPtr NewJPEGWorld(short depth, Rect theRect)
- {
- OSErr err;
- GWorldPtr theWorld = nil;
- GWorldPtr oldPort;
- PixMapHandle thePix;
- CTabHandle cTab = nil;
- GDHandle oldGD;
-
- GetGWorld(&oldPort,&oldGD);
-
- // if depth is greater than 32 then the
- // image is grayscale
- if (depth > 32)
- {
- cTab = GetCTable(depth);
- depth = depth - 32;
- }
-
- err = NewGWorld(&theWorld, depth, &theRect, cTab, nil, 0L); // try our heap
-
- if (err != noErr)
- err = NewGWorld(&theWorld, depth,
- &theRect, cTab, nil, useTempMem); // else try temp
-
- if (err == noErr && theWorld != nil)
- {
- thePix = GetGWorldPixMap(theWorld);
-
- if (LockPixels(thePix))
- {
- SetGWorld(theWorld, nil);
- EraseRect(&theRect);
-
- UnlockPixels(thePix);
- }
- }
-
- SetGWorld(oldPort, oldGD);
-
- return theWorld;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // DoSaveJPEG -
- //
- //
- //----------------------------------------------------------------------
-
- OSErr SaveJPEGFile(StandardFileReply reply, WindowRef window)
- {
- OSErr err = noErr;
- ImageDescriptionHandle desc;
- Handle data;
- Str255 str;
- Rect srcRect;
- GWorldPtr theWorld;
- PixMapHandle thePix;
- CTabHandle cTab = nil;
- ICMFlushProcRecord flushProc;
- long size;
- long dataSize;
- short refNum;
- short depth;
- Str255 title;
- DocHnd doc;
-
-
- GetWTitle(window, title);
-
- doc = (DocHnd)GetWRefCon(window);
-
- if (reply.sfGood && doc != nil)
- {
- desc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
-
- theWorld = (**doc).world;
-
- if (theWorld != nil && desc != nil)
- {
- srcRect = theWorld->portRect;
- thePix = GetGWorldPixMap(theWorld);
-
- if (LockPixels(thePix))
- {
- depth = (**thePix).pixelSize;
- if (depth < 16)
- cTab = (**thePix).pmTable;
-
- data = NewHandle(kBufferSize);
- err = MemError();
-
- if (data != nil && err == noErr)
- {
- HLock(data);
-
- if (reply.sfReplacing )
- err = FSpDelete(&reply.sfFile);
-
- err = FSpCreate(&reply.sfFile, 'JVWR', kJPEGType, reply.sfScript);
-
- if (err == noErr)
- err = FSpOpenDF(&reply.sfFile,fsRdWrPerm, &refNum);
-
- if (err == noErr)
- err = SetFPos(refNum, fsFromStart , 0);
-
- if (err == noErr)
- {
- flushProc.flushProc = NewICMFlushProc(DataUnloadProc);
- flushProc.flushRefCon = refNum;
-
- err = FCompressImage(thePix, &srcRect, depth,
- codecNormalQuality, 'jpeg',
- bestCompressionCodec, cTab,
- codecFlagWasCompressed, kBufferSize,
- &flushProc, nil, desc, *data);
- }
-
- if (err == noErr)
- err = SetFPos(refNum, fsFromStart, (**desc).dataSize);
-
- if (err == noErr)
- err = SetEOF(refNum, (**desc).dataSize);
-
- if (err == noErr)
- err = FSClose( refNum );
-
- HUnlock(data);
- DisposeHandle(data);
-
- DisposeRoutineDescriptor(flushProc.flushProc);
-
- if (cTab != nil)
- DisposeCTable(cTab);
- }
-
- }
-
- UnlockPixels(thePix);
-
- }
- DisposeHandle((Handle)desc);
- }
- else
- err = dsMemFullErr;
-
- return err;
-
- }
-
-
-
- //----------------------------------------------------------------------
- //
- // DataUnloadProc -
- //
- //
- //----------------------------------------------------------------------
-
- pascal OSErr DataUnloadProc(Ptr data, long bytesNeeded, long refCon)
- {
- OSErr err;
-
- if (data == nil)
- {
- err = SetFPos(refCon, fsCurPerm, bytesNeeded);
- }
- else
- {
- err = FSWrite(refCon, &bytesNeeded, data);
- }
-
- return err;
-
- }